package exercise;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;

public class MainFrame extends JFrame {
    ArrayList<UserData> userData;
    final String save = "Data.bin";
    File saveLoc;
    ObjectInputStream is;
    ObjectOutputStream os;
    JLabel title;
    JPanel north;
    InputPanelSet inputSet;
    ChoiceButtonsSet choices;
    public static void main(String[] args) {
        new MainFrame();
    }
    MainFrame() {
        userData = new ArrayList<>();
        READ:
        {
            try {
                saveLoc = new File(save);
                is = new ObjectInputStream(new FileInputStream(save));
            } catch (IOException ioException) {
                JOptionPane.showMessageDialog(this,
                        "未找到账号数据，将会保存至新建的" + save);
                break READ;
            }
            while (true) {
                try {
                    UserData user = (UserData) is.readObject();
                    if (user == null) break;
                    userData.add(user);
                } catch (ClassNotFoundException | IOException exception) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        JOptionPane.showMessageDialog(this,"读取"+save+"出错");
                        System.exit(0);
                    }
                    break;
                }
            }
        }

        setLayout(new GridBagLayout());
        setTitle("登录");

        title = new JLabel("登录");
        title.setFont(new Font("Times New Roman", Font.BOLD, 30));
        title.setHorizontalAlignment(SwingConstants.CENTER);
        north = new JPanel();
        //north.add(title);
        add(north, myConstraints(0, 0));

        inputSet = new InputPanelSet(false);
        add(inputSet, myConstraints(0, 1));
        choices = new ChoiceButtonsSet(null);
        add(choices, myConstraints(0, 2));

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                saveData();
            }
        });

        setSize(0x200, 0x200);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }
    class RegisterFrame extends JFrame {
        InputPanelSet inputs;
        ChoiceButtonsSet choices;
        RegisterFrame() {
            setLayout(new GridBagLayout());

            add(inputs = new InputPanelSet(true), myConstraints(0, 0));
            add(choices = new ChoiceButtonsSet(this), myConstraints(0, 1));
            setTitle("注册");
            setSize(0x200, 0x200);
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setVisible(true);
        }
    }

    static class InputPanelSet extends JPanel {
        InputPanel name, password, verify;

        InputPanelSet(boolean toVerify) {
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            name = new InputPanel("姓名", false);
            password = new InputPanel("密码", true);
            add(name);
            add(password);
            if (toVerify) {
                verify = new InputPanel("确认密码", true);
                add(verify);
            }
        }
    }

    class ChoiceButtonsSet extends JPanel {
        JButton register, confirm, cancel;
        RegisterFrame registerFrame;

        ChoiceButtonsSet(RegisterFrame registerFrame) {
            this();
            if (registerFrame == null) {
                register = new JButton("注册");
                register.addActionListener(e -> new RegisterFrame().setVisible(true));
                add(register);
                confirm.addActionListener(e -> {
                    for (UserData user : MainFrame.this.userData) {
                        if (user.valid(
                                MainFrame.this.inputSet.name.input.getText(),
                                Arrays.toString(MainFrame.this.inputSet.password.
                                        passwordGetter.getPassword())
                        )) {
                            JOptionPane.showMessageDialog(
                                    MainFrame.this,
                                    "登陆成功");
                            return;
                        }
                    }
                    JOptionPane.showMessageDialog(
                            MainFrame.this,
                            "账号或密码错误");
                });
                cancel.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseClicked(MouseEvent e) {
                        JOptionPane.showMessageDialog(
                                ChoiceButtonsSet.this,
                                "欢迎下次使用");
                        MainFrame.this.saveData();
                    }
                });
            }
            else {
                this.registerFrame = registerFrame;
                confirm.addActionListener(e -> {
                    String name = registerFrame.inputs.name.input.getText(),
                            password = Arrays.toString(registerFrame.inputs.password.passwordGetter.getPassword()),
                            verify = Arrays.toString(registerFrame.inputs.verify.passwordGetter.getPassword());
                    for (UserData user : MainFrame.this.userData) {
                        if (user.name.equals(name)) {
                            JOptionPane.showMessageDialog(MainFrame.this, "账号已存在");
                            return;
                        }
                    }
                    if (password.equals(verify)) {
                        MainFrame.this.userData.add(new UserData(name, password));
                        JOptionPane.showMessageDialog(registerFrame, "账号注册成功");
                        registerFrame.setVisible(false);
                        MainFrame.this.inputSet.name.input.setText(name);
                        MainFrame.this.inputSet.password.passwordGetter.setText(password);
                        registerFrame.dispose();
                    } else {
                        JOptionPane.showMessageDialog(
                                MainFrame.this,
                                "密码验证错误");
                    }
                });
                cancel.addActionListener(e-> registerFrame.dispose());
            }
        }

        ChoiceButtonsSet() {
            confirm = new JButton("确认");
            add(confirm);
            cancel = new JButton("取消");

            add(cancel);
        }

    }

    static GridBagConstraints myConstraints(int x, int y) {
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.gridx = x;
        constraints.gridy = y;
        return constraints;
    }
    void saveData(){
        try{
            os = new ObjectOutputStream(new FileOutputStream(save));
            for(UserData user:userData){
                os.writeObject(user);
            }
            System.exit(0);
        }catch (Exception exception){
            JOptionPane.showMessageDialog(this,"无法写入 "+save);
            System.exit(1);
        }
    }
}
class UserData implements Serializable{
    String name,password;

    public UserData(String name, String password) {
        this.name = name;
        this.password = password;
    }
    public boolean valid(String name, String password){
        return this.name.equals(name)
                &&this.password.equals(password);
    }
}
class InputPanel extends JPanel{
    JLabel prompt;
    JTextField input;
    JPasswordField passwordGetter;
    public InputPanel(String prompt,boolean hide) {
        this.prompt = new JLabel(prompt);
        add(this.prompt);
        if(hide){
            passwordGetter=new JPasswordField(0x10);
            add(passwordGetter);
        }else{
            this.input = new JTextField(0x10);
            add(input);
            input.setVisible(true);
        }
        this.prompt.setVisible(true);
    }
}